<?php

namespace App\Http\Middleware;

use App\Services\LogService;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

/**
 * 日志中间件
 * 自动记录API请求和响应日志
 */
class LoggingMiddleware
{
    public function __construct(
        private LogService $logService
    ) {}

    /**
     * 处理传入请求
     */
    public function handle(Request $request, Closure $next): Response
    {
        $startTime = microtime(true);

        // 获取用户信息
        $user = Auth::user();
        $userId = $user?->id;
        $username = $user?->username ?? 'guest';

        // 记录请求开始
        $this->logRequest($request, $userId, $username);

        // 处理请求
        $response = $next($request);

        $endTime = microtime(true);
        $duration = round(($endTime - $startTime) * 1000, 2); // 毫秒

        // 记录响应
        $this->logResponse($request, $response, $userId, $username, $duration);

        return $response;
    }

    /**
     * 记录请求日志
     */
    private function logRequest(Request $request, ?int $userId, string $username): void
    {
        // 只记录重要的API请求
        if ($this->shouldLogRequest($request)) {
            try {
                // 使用SystemLog的静态方法记录
                \App\Models\SystemLog::create([
                    'user_id' => $userId,
                    'username' => $username,
                    'operation_type' => 'read', // 默认请求为读取操作
                    'operation_name' => $this->getOperationName($request->method()),
                    'module' => $this->getModuleFromPath($request->path()),
                    'action' => $request->method(),
                    'target_type' => null,
                    'target_id' => null,
                    'description' => "API请求: {$request->method()} {$request->path()}",
                    'ip_address' => $request->ip(),
                    'user_agent' => $request->userAgent(),
                    'level' => $this->getLogLevel($request),
                    'request_method' => $request->method(),
                    'request_url' => $request->fullUrl(),
                    'request_data' => $this->getRequestData($request),
                    'source' => 'api',
                    'session_id' => session()->getId(),
                    'duration' => null, // 请求开始时duration为null
                ]);
            } catch (\Exception $e) {
                // 记录日志失败不影响正常业务
                \Illuminate\Support\Facades\Log::error('请求日志记录失败', [
                    'error' => $e->getMessage(),
                    'request' => $request->fullUrl(),
                ]);
            }
        }
    }

    /**
     * 记录响应日志
     */
    private function logResponse(Request $request, Response $response, ?int $userId, string $username, float $duration): void
    {
        // 只记录重要的API响应
        if ($this->shouldLogRequest($request)) {
            try {
                \App\Models\SystemLog::create([
                    'user_id' => $userId,
                    'username' => $username,
                    'operation_type' => $this->getOperationTypeFromMethod($request->method()),
                    'operation_name' => $this->getOperationName($request->method()),
                    'module' => $this->getModuleFromPath($request->path()),
                    'action' => $request->method(),
                    'target_type' => null,
                    'target_id' => null,
                    'description' => "API响应: {$request->method()} {$request->path()} - HTTP {$response->getStatusCode()}",
                    'ip_address' => $request->ip(),
                    'user_agent' => $request->userAgent(),
                    'level' => $this->getResponseLogLevel($response),
                    'request_method' => $request->method(),
                    'request_url' => $request->fullUrl(),
                    'response_status' => $response->getStatusCode(),
                    'response_message' => $this->getResponseMessage($response),
                    'source' => 'api',
                    'session_id' => session()->getId(),
                    'duration' => $duration,
                ]);
            } catch (\Exception $e) {
                // 记录日志失败不影响正常业务
                \Illuminate\Support\Facades\Log::error('响应日志记录失败', [
                    'error' => $e->getMessage(),
                    'request' => $request->fullUrl(),
                    'response_status' => $response->getStatusCode(),
                ]);
            }
        }
    }

    /**
     * 判断是否应该记录请求
     */
    private function shouldLogRequest(Request $request): bool
    {
        $path = $request->path();

        // 不记录的路径
        $excludedPaths = [
            'api/test',
            'api/constants',
            'api/permissions/user',
            'api/permissions/all',
            'api/permissions/modules',
            'api/permissions/roles',
        ];

        foreach ($excludedPaths as $excludedPath) {
            if (str_contains($path, $excludedPath)) {
                return false;
            }
        }

        // 只记录API路径
        return str_starts_with($path, 'api/');
    }

    /**
     * 获取操作名称
     */
    private function getOperationName(string $method): string
    {
        $methodNames = [
            'GET' => '查询',
            'POST' => '创建',
            'PUT' => '更新',
            'PATCH' => '部分更新',
            'DELETE' => '删除',
        ];

        return $methodNames[$method] ?? $method;
    }

    /**
     * 根据HTTP方法获取操作类型
     */
    private function getOperationTypeFromMethod(string $method): string
    {
        return match ($method) {
            'GET' => 'read',
            'POST' => 'create',
            'PUT', 'PATCH' => 'update',
            'DELETE' => 'delete',
            default => 'read'
        };
    }

    /**
     * 从路径获取模块名称
     */
    private function getModuleFromPath(string $path): string
    {
        $segments = explode('/', $path);

        if (count($segments) >= 2) {
            $module = $segments[1]; // api/{module}/...

            $moduleMap = [
                'auth' => '认证',
                'users' => '用户管理',
                'employees' => '员工管理',
                'departments' => '部门管理',
                'positions' => '岗位管理',
                'salaries' => '薪资管理',
                'attendance' => '考勤管理',
                'permissions' => '权限管理',
                'constants' => '常量管理',
                'files' => '文件管理',
                'system' => '系统管理',
            ];

            return $moduleMap[$module] ?? $module;
        }

        return 'unknown';
    }

    /**
     * 获取请求日志级别
     */
    private function getLogLevel(Request $request): string
    {
        // 敏感操作使用warning级别
        if (in_array($request->method(), ['POST', 'PUT', 'DELETE'])) {
            return 'info';
        }

        return 'debug';
    }

    /**
     * 获取响应日志级别
     */
    private function getResponseLogLevel(Response $response): string
    {
        $statusCode = $response->getStatusCode();

        if ($statusCode >= 500) {
            return 'critical';
        } elseif ($statusCode >= 400) {
            return 'error';
        } elseif ($statusCode >= 300) {
            return 'warning';
        } else {
            return 'info';
        }
    }

    /**
     * 获取请求数据（过滤敏感信息）
     */
    private function getRequestData(Request $request): ?array
    {
        $data = $request->all();

        // 过滤敏感字段
        $sensitiveFields = ['password', 'token', 'secret', 'key'];
        foreach ($sensitiveFields as $field) {
            if (isset($data[$field])) {
                $data[$field] = '[FILTERED]';
            }
        }

        // 只记录有意义的数据
        return !empty($data) ? $data : null;
    }

    /**
     * 获取响应消息
     */
    private function getResponseMessage(Response $response): ?string
    {
        // 如果是JSON响应，尝试解析消息
        if ($response->headers->get('content-type') === 'application/json') {
            try {
                $content = json_decode($response->getContent(), true);
                if (is_array($content) && isset($content['message'])) {
                    return $content['message'];
                }
            } catch (\Exception $e) {
                // JSON解析失败，不记录消息
            }
        }

        return null;
    }
}
